import pandas as pd
import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, r2_score, mean_absolute_error
from sklearn.model_selection import train_test_split


class MultiLinearRegression(object):
    """
    多元线性回归
    """
    def __init__(self, fit_intercept=True, copy_x=True, n_jobs=None, positive=False):
        self.mlr = LinearRegression(
            fit_intercept=fit_intercept,
            copy_X=copy_x,
            n_jobs=n_jobs,
            positive=positive
        )
        self.x_train = None
        self.y_train = None
        self.n = None
        self.m = None

    def init_data(self, x_train, y_train):
        """
        param: x_train
        param: y_train
        return:
        """
        (m, n) = np.shape(x_train)
        tem_m = np.shape(y_train)
        try:
            if m != tem_m[0]:
                raise ValueError
            self.x_train = x_train
            self.y_train = y_train
            self.n = n
            self.m = m
        except ValueError:
            print("数据出错，x,y样本不一致")
            return

    def fit(self, x_train, y_train, sample_weight=None):
        self.init_data(x_train, y_train)
        self.mlr.fit(x_train, y_train, sample_weight)

    def predict(self, x_test):
        (m, n) = np.shape(x_test)
        try:
            if n != self.n:
                raise ValueError
            self.y_pred = self.mlr.predict(x_test)
            return self.y_pred
        except ValueError:
            print("输入数据维度不对，模型维度应该为：", self.n)
            return

    def init_set(self):
        pass

    def set_hyperpara(self):
        pass

    def get_mse(self, y_test):
        """ 均方误差:MSE """
        return mean_squared_error(y_test, self.y_pred)

    def get_rmse(self, y_test):
        """ 均方根误差:RMSE """
        return np.sqrt(mean_squared_error(y_test, self.y_pred))

    def get_mae(self, y_test):
        """ 平均绝对误差:MAE """
        return mean_absolute_error(y_test, self.y_pred)

    def get_score(self, y_test, sample_weight=None):
        """R^2"""
        return r2_score(y_test, self.y_pred, sample_weight=sample_weight)


if __name__ == '__main__':

    new_pumpkins = pd.read_csv("../test_file/new_pumpkins.csv")  # 利用pandas库打开csv数据
    new_pumpkins.info()
    # 多元线性回归
    X = pd.get_dummies(new_pumpkins['Variety']) \
        .join(new_pumpkins['Month']) \
        .join(pd.get_dummies(new_pumpkins['City'])) \
        .join(pd.get_dummies(new_pumpkins['Package']))
    Y = new_pumpkins['Price']
    X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.2, random_state=0)
    lin_reg = MultiLinearRegression()
    lin_reg.fit(X_train, Y_train)
    predict = lin_reg.predict(X_test)
    rmse = lin_reg.get_rmse(Y_test)
    score = lin_reg.get_score(Y_test)

    print(
        f'Mean error: {rmse:3.3} ({rmse / np.mean(predict) * 100:3.3}%)')  # 输出均方误差的值以及错误率 score = lin_reg.score(X_train,Y_train)#计算回归系数
    print('Model determination: ', score)  # 输出回归系数的值
